use core::marker::PhantomData;

use cmsis_rtos2_rs::static_mem::Mutex;
use utils::{
    log::{set_log_writer, LogWriter, MutByteRef},
    ByteBuffer,
};

pub trait Write2 {
    fn write(buf: &[u8]);
}

pub struct Logger<W: Write2, const SIZE: usize> {
    _w: PhantomData<W>,
    mutex: Mutex,
    buf: ByteBuffer<SIZE>,
}

impl <W: Write2, const SIZE: usize> Logger<W, SIZE> {

    pub const fn uninit() -> Self {
        Self { _w: PhantomData, mutex: Mutex::uninit(), buf: ByteBuffer::const_new() }
    }

    pub unsafe fn init_once(&'static self) {
        self.mutex.init_once("logger");
        set_log_writer(self);
    }
}

impl<W: Write2, const SIZE: usize> LogWriter for Logger<W, SIZE> {

    fn flush<'a>(&self, bytes: MutByteRef<'a>) {
        W::write(bytes.data());
        unsafe {
            self.mutex.unlock();
        }
    }

    fn wr<'a>(&'a self) -> MutByteRef<'a> {
        unsafe {
            self.mutex.lock();
            MutByteRef::new(self.buf.as_mut_slice())
        }
    }
}
